/*
 * Copyright (c) 2013, Ivan Babushkin.
 */
package asngen.codec;

import asngen.core.AsnInteger;

import java.io.DataOutputStream;
import java.io.IOException;

class IntegerEncoderRuntime {
    private DataOutputStream dos;
    protected AsnInteger value;
    protected int size;

    public IntegerEncoderRuntime(DataOutputStream dos, AsnInteger value) {
        this.value = value;
        this.dos = dos;
    }

    protected void twosComplement() throws IOException {
        switch (size) {
            case 1:
                dos.writeByte((byte) value.getValue()); break;
            case 2:
                dos.writeShort((short) value.getValue()); break;
            case 3:
                dos.writeByte((byte) (value.getValue() >> 16));
                dos.writeShort((short) value.getValue());
                break;
            case 4:
                dos.writeInt((int) value.getValue()); break;
            case 5:
                dos.writeByte((byte) (value.getValue() >> 32));
                dos.writeInt((int) value.getValue());
                break;
            case 6:
                dos.writeShort((short) (value.getValue() >> 32));
                dos.writeInt((int) value.getValue());
                break;
            case 7:
                dos.writeByte((byte) (value.getValue() >> 48));
                dos.writeShort((short) (value.getValue() >> 32));
                dos.writeInt((int) value.getValue());
                break;
            default:
                dos.writeLong(value.getValue()); break;
        }
    }

    protected void positiveInt() throws IOException {
        twosComplement();
    }

    protected void fixedToMax() {
        long leftBound = value.getLeftBound();
        long rightBound = value.getRightBound();
        if (leftBound >= 0) {
            if (rightBound < 0x100L) {
                size = 1;
            } else if (rightBound < 0x10000L) {
                size = 2;
            } else if (rightBound < 0x1000000L) {
                size = 4;
            } else {
                size = 8;
            }
        } else {
            if ((leftBound >= -128L) && (rightBound <= 127L)) {
                size = 1;
            } else if ((leftBound >= -32768L) && (rightBound <= 32767L)) {
                size = 2;
            } else if ((leftBound >= -2147483648L) && (rightBound <= 2147483647L)) {
                size = 4;
            } else {
                size = 8;
            }
        }
    }

    protected boolean boundedWithNegatives() {
        return value.getLeftBound() < 0;
    }

    protected boolean boundedWithoutNegatives() {
        return value.getLeftBound() >= 0;
    }
}
